home *** CD-ROM | disk | FTP | other *** search
/ Aminet 5 / Aminet 5 - March 1995.iso / Aminet / util / arc / VEC_3_231.lha / vec3231 / source / vdc.c < prev    next >
C/C++ Source or Header  |  1993-12-08  |  17KB  |  1,020 lines

  1. /*
  2.  * VDC.C (VEC)
  3.  *
  4.  * Copyright (c) 1991, 1992, 1993 Ville Saari
  5.  * All rights reserved
  6.  *
  7.  * Created: 23-Dec-91
  8.  * Updated: 05-Dec-93
  9.  */
  10.  
  11. #include "vec.h"
  12.  
  13. #define MC 181
  14. #define UC 252
  15. #define EC 253 
  16. #define HW 254
  17. #define VW 255
  18.  
  19. #define hws(c) (decodetab[c]==HW)
  20. #define vws(c) (decodetab[c]==VW)
  21. #define ws(c) (decodetab[c]>=HW)
  22.  
  23. const static unsigned char decodetab[256]=
  24.     {
  25.     /* unused characters, white space characters and end character: */
  26.  
  27.     UC, UC, UC, UC, UC, UC, UC, UC, UC, HW, VW, VW, UC, VW, UC, UC,
  28.     UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC,
  29.     HW, EC, UC, UC,
  30.  
  31.     /* bytes used by all methods: */
  32.  
  33.     0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15,
  34.     16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
  35.     32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
  36.     48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
  37.  
  38.     /* additional bytes for >=6.5 bit methods: */
  39.  
  40.     64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
  41.     80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
  42.  
  43.     /* unused characters */
  44.  
  45.     UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC,
  46.     UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC,
  47.  
  48.     /* additional bytes for >=7 bit methods: */
  49.  
  50.      91,  92,  93,  94,  95,  96,  97,  98,  99, 100,
  51.     101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
  52.     111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
  53.     121, 122, 123, 124, 125, 126, 127,
  54.  
  55.     /* additional bytes for 7.5 bit method: */
  56.  
  57.     128, 129, 130, 131, 132, 133, 134, 135, 136, 137,
  58.     138, 139, 140, 141, 142, 143, 144, 145, 146, 147,
  59.     148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
  60.     158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
  61.     168, 169, 170,    171, 172, 173, 174, 175, 176, 177,
  62.     178, 179, 180,    181,
  63.  
  64.     /* unused characters */
  65.  
  66.     UC, UC, UC, UC
  67.     };
  68.  
  69. static unsigned char uudecodetab[256];
  70.  
  71. static struct namedata
  72.     {
  73.     struct namedata *next;
  74.     int count;
  75.     char name[1];
  76.     } *ndbase=0;
  77.  
  78. static unsigned char *start;
  79. static unsigned char linedelim;
  80.  
  81. static void sevenandhalfbitdecoder(const unsigned char *i, unsigned char *o)
  82.     {
  83.     unsigned int z;
  84.     unsigned char *p=o+8;
  85.  
  86.     z=*i++; z+=182**i++; *o++=z; *p++=z>>8;
  87.     z=*i++; z+=182**i++; *o++=z; *p++=z>>8;
  88.     z=*i++; z+=182**i++; *o++=z; *p++=z>>8;
  89.     z=*i++; z+=182**i++; *o++=z; *p++=z>>8;
  90.     z=*i++; z+=182**i++; *o++=z; *p++=z>>8;
  91.     z=*i++; z+=182**i++; *o++=z; *p++=z>>8;
  92.     z=*i++; z+=182**i++; *o++=z; *p  =z>>8;
  93.     z=*i++; z+=182**i  ; *o++=z;
  94.  
  95.     *o++|=(z>>=1)&0x80;
  96.     *o++|=(z>>=1)&0x80;
  97.     *o++|=(z>>=1)&0x80;
  98.     *o++|=(z>>=1)&0x80;
  99.     *o++|=(z>>=1)&0x80;
  100.     *o++|=(z>>=1)&0x80;
  101.     *o  |=(z>>=1)&0x80;
  102.     }
  103.  
  104. static void sevenbitdecoder(const unsigned char *i, unsigned char *o)
  105.     {
  106.     unsigned int z;
  107.  
  108.     z=i[7];
  109.     *o++=*i++|(z<<7);
  110.     *o++=*i++|(z<<6)&0x80;
  111.     *o++=*i++|(z<<5)&0x80;
  112.     *o++=*i++|(z<<4)&0x80;
  113.     *o++=*i++|(z<<3)&0x80;
  114.     *o++=*i++|(z<<2)&0x80;
  115.     *o  =*i  |(z<<1)&0x80;
  116.     }
  117.  
  118. static void sixandhalfbitdecoder(const unsigned char *i, unsigned char *o)
  119.     {
  120.     unsigned int z;
  121.     unsigned char *p=o+8;
  122.  
  123.     z=*i++; z+=91**i++; *o++=z; *p++=z>>8;
  124.     z=*i++; z+=91**i++; *o++=z; *p++=z>>8;
  125.     z=*i++; z+=91**i++; *o++=z; *p++=z>>8;
  126.     z=*i++; z+=91**i++; *o++=z; *p++=z>>8;
  127.     z=*i++; z+=91**i++; *o++=z; *p  =z>>8;
  128.  
  129.     z=*i++; z+=91**i++; *o++=z;
  130.     p[-4]|=(z>>3)&0xe0;
  131.     p[-1]|=(z>>6)&0x60;
  132.  
  133.     z=*i++; z+=91**i++; *o++=z;
  134.     p[-3]|=(z>>3)&0xe0;
  135.     p[ 0]|=(z>>6)&0x60;
  136.  
  137.     z=*i++; z+=91**i; *o=z;
  138.     p[-2]|=(z>>3)&0xe0;
  139.     p[-1]|=(z>>4)&0x80;
  140.     p[ 0]|=(z>>5)&0x80;
  141.     }
  142.  
  143. static void sixbitdecoder(const unsigned char *i, unsigned char *o)
  144.     {
  145.     unsigned int z;
  146.  
  147.     z=i[6];
  148.     *o++=*i++|(z<<6)&0xc0;
  149.     *o++=*i++|(z<<4)&0xc0;
  150.     *o++=*i++|(z<<2)&0xc0;
  151.  
  152.     z=i[4];
  153.     *o++=*i++|(z<<6)&0xc0;
  154.     *o++=*i++|(z<<4)&0xc0;
  155.     *o  =*i  |(z<<2)&0xc0;
  156.     }
  157.  
  158. static int gethexval(unsigned char val)
  159.     {
  160.     return val-(val<25?12:val<48?19:51);
  161.     }
  162.  
  163. static void hexdecoder(const unsigned char *i, unsigned char *o)
  164.     {
  165.     *o=gethexval(i[0])<<4|gethexval(i[1]);
  166.     }
  167.  
  168. static int fecdecoder(void)
  169.     {
  170.     int c;
  171.  
  172.     do    {
  173.         if(inptr>=inbufend && !fillbuffer(1)) return -7;
  174.         c=*inptr++;
  175.         }
  176.     while(vws(c));
  177.  
  178.     if(c>=248) return c==248?-7:-c+248;
  179.  
  180.     return c-(c>159?65:33);
  181.     }
  182.  
  183. static int btoadecoder(unsigned char *buf)
  184.     {
  185.     int c;
  186.     unsigned long z;
  187.  
  188.     do    {
  189.         if(inptr>=inbufend && !fillbuffer(1)) return 0;
  190.         c=*inptr++;
  191.         }
  192.     while(vws(c));
  193.  
  194.     if(c=='z')
  195.         {
  196.         buf[0]=buf[1]=buf[2]=buf[3]=0;
  197.         return 1;
  198.         }
  199.  
  200.     if(c=='x') return 0;
  201.  
  202.     z=((unsigned long)(c-'!'))*(85*85*85*85);
  203.  
  204.     do    {
  205.         if(inptr>=inbufend && !fillbuffer(1)) return 0;
  206.         c=*inptr++;
  207.         }
  208.     while(vws(c));
  209.  
  210.     z+=((unsigned long)(c-'!'))*(85*85*85);
  211.  
  212.     do    {
  213.         if(inptr>=inbufend && !fillbuffer(1)) return 0;
  214.         c=*inptr++;
  215.         }
  216.     while(vws(c));
  217.  
  218.     z+=((unsigned long)(c-'!'))*(85*85);
  219.  
  220.     do    {
  221.         if(inptr>=inbufend && !fillbuffer(1)) return 0;
  222.         c=*inptr++;
  223.         }
  224.     while(vws(c));
  225.  
  226.     z+=((unsigned long)(c-'!'))*85;
  227.  
  228.     do    {
  229.         if(inptr>=inbufend && !fillbuffer(1)) return 0;
  230.         c=*inptr++;
  231.         }
  232.     while(vws(c));
  233.  
  234.     z+=(unsigned long)(c-'!');
  235.  
  236.     *buf++=(unsigned char)(z>>24);
  237.     *buf++=(unsigned char)(z>>16);
  238.     *buf++=(unsigned char)(z>>8);
  239.     *buf  =(unsigned char)z;
  240.  
  241.     return 1;
  242.     }
  243.  
  244. static void getname(const char *from, char *to, const char *s)
  245.     {
  246.     struct namedata *nd;
  247.  
  248.     strncpy(to, from, 256);
  249.  
  250.     for(nd=ndbase; nd; nd=nd->next)
  251.         if(!strcmp(nd->name, from))
  252.             {
  253.             nd->count++;
  254.  
  255.             modifyname(to, nd->count);
  256.  
  257.             if(!silent)
  258.                 {
  259.                 printerr(from);
  260.                 printerr(" -> ");
  261.                 printerr(to);
  262.                 printerr(s);
  263.                 }
  264.  
  265.             return;
  266.             }
  267.  
  268.     if(nd=(struct namedata *)malloc(strlen(to)+sizeof *nd))
  269.         {
  270.         strcpy(nd->name, to);
  271.         nd->count=0;
  272.         nd->next=ndbase;
  273.         ndbase=nd;
  274.         }
  275.  
  276.     if(!silent)
  277.         {
  278.         printerr(to);
  279.         printerr(s);
  280.         }
  281.     }
  282.  
  283. static int getline(unsigned char *buf, int size)
  284.     {
  285.     unsigned char c=0, *e=buf+size;
  286.  
  287.     do    {
  288.         if(inptr>=inbufend && !fillbuffer(1)) goto end;
  289.         c=*inptr++;
  290.         }
  291.     while(vws(c));
  292.  
  293.     do    {
  294.         *buf++=c;
  295.         if(inptr>=inbufend && !fillbuffer(1)) break;
  296.         c=*inptr++;
  297.         }
  298.     while(!vws(c) && buf<e);
  299.  
  300. end:
  301.     linedelim=c;
  302.     *buf=0;
  303.  
  304.     return size-(e-buf);
  305.     }
  306.  
  307. static int myfile;
  308. static unsigned char namebuf[256];
  309.  
  310. static void startoutput(const unsigned char *filename, const unsigned char *method)
  311.     {
  312.     if(lines==1)
  313.         {
  314. #ifdef FINNISH
  315.         writefile(stdoutfile, "### Koodattu tiedosto poistettu: ", 33);
  316. #else
  317.         writefile(stdoutfile, "### Encoded file removed: ", 26);
  318. #endif
  319.         writefile(stdoutfile, filename, strlen(filename));
  320.         writefile(stdoutfile, method, strlen(method));
  321.         }
  322.  
  323.     if(outfileflag || pipe)
  324.         {
  325.         if(!silent)
  326.             {
  327.             printerr(filename);
  328.             printerr(method);
  329.             }
  330.  
  331.         myfile=0;
  332.         }
  333.     else
  334.         {
  335.         getname(filename, namebuf, method);
  336.  
  337.         if(failedopen(outfile=openwrite(namebuf, 1)))
  338.             {
  339. #ifdef FINNISH
  340.             printerrh("Tiedosto `");
  341.             printerr(namebuf);
  342.             printerr("' ei aukea.\n");
  343. #else
  344.             printerrh("Can't open output file `");
  345.             printerr(namebuf);
  346.             printerr("'.\n");
  347. #endif
  348.             errcleanup(0);
  349.             }
  350.  
  351.         outfileflag=myfile=1;
  352.         }
  353.     }
  354.  
  355. static void endoutput(const unsigned char *flags)
  356.     {
  357.     if(!myfile) return;
  358.  
  359.     flushoutput();
  360.     closefile(outfile);
  361.     outfileflag=myfile=0;
  362.  
  363.     if(flags && !nomode) setfilemode(namebuf, flags);
  364.     }
  365.  
  366. static unsigned long illegal;
  367.  
  368. static int getvecblock(char *p, int size)
  369.     {
  370.     unsigned int c, r;
  371.     unsigned char *b;
  372.  
  373.     do    {
  374.         b=get(r=size);
  375.  
  376.         if(trueread<size)
  377.             {
  378.             if(trueread && *b=='!') b++;
  379.             inptr=b;
  380.             return 0;
  381.             }
  382.  
  383.         while(r--)
  384.             {
  385.             if((c=decodetab[*b++])>MC)
  386.                 {
  387.                 if(c==EC)
  388.                     {
  389.                     inptr=b;
  390.                     return 0;
  391.                     }
  392.                 if(c==UC) illegal++;
  393.                 }
  394.             else
  395.                 {
  396.                 *p++=c;
  397.                 size--;
  398.                 }
  399.             }
  400.         }
  401.     while(size);
  402.  
  403.     return 1;
  404.     }
  405.  
  406. static unsigned short updatecrc(unsigned short crc, const unsigned char *p, unsigned long size)
  407.     {
  408.     while(size--) crc=(crc>>8)^crc16tab[(unsigned char)(crc^*p++)];
  409.     return crc;
  410.     }
  411.  
  412. static int decodevec(unsigned char *linebuf)
  413.     {
  414.     unsigned char flags[6], inblockbuf[16], *p, *startptr=outptr;
  415.     void (*decoder)(const unsigned char *, unsigned char *);
  416.     int inblock, outblock, makecrc, crc, t, ok=1;
  417.  
  418.     *linebuf=0;
  419.     crc=0;
  420.     illegal=0;
  421.  
  422.     if(strlen(linebuf+1)<14)
  423.         {
  424. #ifdef FINNISH
  425.         printerr("Virheellinen vec headeri!\n");
  426. #else
  427.         printerr("Corrupted vec header!\n");
  428. #endif
  429.         return 0;
  430.         }
  431.  
  432.     for(p=linebuf+7; p<linebuf+15; p++) *p=decodetab[*p];
  433.  
  434.     sixbitdecoder(linebuf+7, flags);
  435.  
  436.     if(linebuf[15])
  437.         startoutput(linebuf+15, "\n");
  438.     else
  439.         startoutput("noname", "\n");
  440.  
  441.     makecrc=((flags[0]&1) && !quick);
  442.  
  443.     switch(linebuf[6])
  444.         {
  445.         case '3':
  446.             decoder=sevenandhalfbitdecoder;
  447.             inblock=16;
  448.             outblock=15;
  449.             break;
  450.  
  451.         case '2':
  452.             decoder=sevenbitdecoder;
  453.             inblock=8;
  454.             outblock=7;
  455.             break;
  456.  
  457.         case '1':
  458.             decoder=sixandhalfbitdecoder;
  459.             inblock=16;
  460.             outblock=13;
  461.             break;
  462.  
  463.         case '0':
  464.             decoder=sixbitdecoder;
  465.             inblock=8;
  466.             outblock=6;
  467.             break;
  468.  
  469.         case 'x':
  470.             decoder=hexdecoder;
  471.             inblock=2;
  472.             outblock=1;
  473.             break;
  474.  
  475.         case 'a':
  476.             inblock=0;
  477.             outblock=0;
  478.             break;
  479.  
  480.         case 'i':
  481.             inblock=0;
  482.             outblock=1;
  483.             break;
  484.  
  485.         default:
  486.             {
  487. #ifdef FINNISH
  488.             static char herja[]="   Tuntematon koodausmenetelm" a_ " ` '!\n";
  489.  
  490.             herja[32]=linebuf[6];
  491.             printerr(herja);
  492. #else
  493.             static char nag[]="   Unknown coding method ` '!\n";
  494.  
  495.             nag[26]=linebuf[6];
  496.             printerr(nag);
  497. #endif
  498.             endoutput(0);
  499.             return 0;
  500.             }
  501.         }
  502.  
  503.     if(inblock)
  504.         {
  505.         while(getvecblock(inblockbuf, inblock))
  506.             {
  507.             if(outptr>=outbufend)
  508.                 {
  509.                 if(makecrc) crc=updatecrc(crc, startptr, outptr-startptr);
  510.                 flushoutput();
  511.                 startptr=outptr;
  512.                 }
  513.  
  514.             decoder(inblockbuf, outptr);
  515.             outptr+=outblock;
  516.             }
  517.         }
  518.     else
  519.         {
  520.         unsigned char c;
  521.         
  522.         for(;;)
  523.             {
  524.             if(inptr>=inbufend && !fillbuffer(1)) break;
  525.             c=*inptr++;
  526.  
  527.             if(c==94 || c==92 && !outblock)
  528.                 {
  529.                 unsigned char c2=c;
  530.  
  531.                 if(inptr>=inbufend && !fillbuffer(1)) break;
  532.                 c=*inptr++;
  533.  
  534.                 if(c2==94)
  535.                     if(vws(c))
  536.                         continue;
  537.                     else if((c&0xe0)==0x40)
  538.                         c-=64;
  539.                     else if((c&0xe0)==0x60)
  540.                         c+=32;
  541.                     else if(c==33)
  542.                         break;
  543.                     else if(c==63)
  544.                         c=127;
  545.                     else if(c==62)
  546.                         c=159;
  547.                     else if(c==61)
  548.                         c=94;
  549.                     else if(c==60 && !outblock)
  550.                         c=92;
  551.                     else if(c==59 && !outblock)
  552.                         c=255;
  553.                     else
  554.                         {
  555.                         if(makecrc) crc=(crc>>8)^crc16tab[(unsigned char)(crc^94)];
  556.                         put1(94);
  557.                         }
  558.                 else
  559.                     c+=128;
  560.                 }
  561.             else if(vws(c) && c!=10)
  562.                 continue;
  563.  
  564.             if(makecrc) crc=(crc>>8)^crc16tab[(unsigned char)(crc^c)];
  565.  
  566.             put1(c);
  567.             }
  568.         }
  569.  
  570.     if(!getvecblock(p=inblockbuf, (inblock?1:0)+(makecrc?4:0)))
  571.         {
  572. #ifdef FINNISH
  573.         printerr("   Tiedosto loppui kesken!\n");
  574. #else
  575.         printerr("   Premature EOF!\n");
  576. #endif
  577.         }
  578.     else
  579.         {
  580.         if(inblock)
  581.             {
  582.             if((t=gethexval(*p++))>outblock || t<0)
  583.                 {
  584. #ifdef FINNISH
  585.                 printerr("   Virheellinen lopetin!\n");
  586. #else
  587.                 printerr("   Incorrect terminator!\n");
  588. #endif
  589.                 }
  590.             else
  591.                 outptr-=t;
  592.  
  593.             crc=updatecrc(crc, startptr, outptr-startptr);
  594.             }
  595.  
  596.         if(makecrc)
  597.             {
  598.             if(crc!=(gethexval(p[0])<<12|gethexval(p[1])<<8|
  599.                 gethexval(p[2])<<4|gethexval(p[3])))
  600.                 {
  601. #ifdef FINNISH
  602.                 printerr("   CRC virhe!\n");
  603. #else
  604.                 printerr("   CRC mismatch!\n");
  605. #endif
  606.                 ok=0;
  607.                 }
  608.             }
  609.         }
  610.  
  611.     if(illegal)
  612.         {
  613. #ifdef FINNISH
  614.         printerr("   Koodi sis" a_ "lsi ");
  615.         if(illegal==1)
  616.             printerr("laittoman merkin!\n");
  617.         else
  618.             {
  619.             printerr(ltoa(illegal));
  620.             printerr(" laitonta merkki" a_ "!\n");
  621.             }
  622. #else
  623.         printerr("   Code contained ");
  624.         if(illegal==1)
  625.             printerr("illegal character!\n");
  626.         else
  627.             {
  628.             printerr(ltoa(illegal));
  629.             printerr(" illegal characters!\n");
  630.             }
  631. #endif
  632.         }
  633.  
  634.     endoutput(flags);
  635.  
  636.     return ok;
  637.     }
  638.  
  639. static void resetuudecodetab(void)
  640.     {
  641.     int f;
  642.  
  643.     for(f=0; f<256; f++)
  644.         uudecodetab[f]=f-' '&0x3f;
  645.     }
  646.  
  647. static int readuudecodetab(unsigned char *linebuf)
  648.     {
  649.     int f, c;
  650.  
  651.     *linebuf=0;
  652.  
  653.     for(f=0; f<64; f++)
  654.         {
  655.         do c=get1(); while(c>=0 && vws(c));
  656.  
  657.         uudecodetab[c]=f;
  658.         }
  659.  
  660.     if((c=get1())<0 || !vws(c))
  661.         {
  662. #ifdef FINNISH
  663.         printerr("Virheellinen uuencodetaulukko!\n");
  664. #else
  665.         printerr("Incorrect uuencode table!\n");
  666. #endif
  667.         resetuudecodetab();
  668.         return 0;
  669.         }
  670.  
  671.     return 1;
  672.     }
  673.  
  674. static int decodeuu(unsigned char *linebuf)
  675.     {
  676.     int ercount=0, sum, n, cont=1;
  677.     unsigned long size=0;
  678.     long mode=0;
  679.     unsigned char c, *p, flagbuf[6];
  680.  
  681.      *linebuf=0;
  682.  
  683.     for(p=linebuf+6; hws(*p); p++);
  684.  
  685.     while(*p>='0' && *p<='7') mode=(mode<<3)|*p++-'0';
  686.  
  687.     while(hws(*p)) p++;
  688.  
  689. #ifdef FINNISH
  690.     startoutput(p, " (uuenkoodattu)\n");
  691. #else
  692.     startoutput(p, " (uuencoded)\n");
  693. #endif
  694.  
  695.     while(cont)
  696.         {
  697.         do {
  698.             if(inptr>=inbufend && !fillbuffer(1))
  699.                 {
  700. #ifdef FINNISH
  701.                 printerr("   Tiedosto loppui kesken!\n");
  702. #else
  703.                 printerr("   Premature EOF!\n");
  704. #endif
  705.                 endoutput(0);
  706.                 return 1;
  707.                 }
  708.  
  709.             c=*inptr++;
  710.             }
  711.         while(vws(c));
  712.  
  713.         sum=0;
  714.  
  715.         size+=n=uudecodetab[c];
  716.  
  717.         p=get((n+2)/3*4+1);
  718.         if(outptr>outbufend-63) flushoutput();
  719.  
  720.         if(!n) cont=0;
  721.  
  722.         while(n>0)
  723.             {
  724.             unsigned char a=uudecodetab[*p++], b;
  725.  
  726.             sum+=*outptr++=a<<2|(b=uudecodetab[*p++])>>4;
  727.             sum+=*outptr++=b<<4|(a=uudecodetab[*p++])>>2;
  728.             sum+=*outptr++=a<<6|   uudecodetab[*p++];
  729.             n-=3;
  730.             }
  731.  
  732.         outptr+=n;
  733.  
  734.         if(!quick && !(vws(*p)) && (sum&0x3f)!=uudecodetab[*p]) ercount++;
  735.         }
  736.  
  737.     flagbuf[2]=2;
  738.     flagbuf[4]=(mode>>8)&0x01;
  739.     flagbuf[5]=mode;
  740.  
  741.     endoutput(flagbuf);
  742.  
  743.     if(ercount)
  744.         {
  745.         printerr("  ");
  746. #ifdef FINNISH
  747.         if(ercount==1)
  748.             printerr("tarkistussummavirhe!\n");
  749.         else
  750.             {
  751.             printerr(ltoa(ercount));
  752.             printerr(" tarkistussummavirhett" a_ "!\n");
  753.             }
  754. #else
  755.         if(ercount==1)
  756.             printerr("checksum error!\n");
  757.         else
  758.             {
  759.             printerr(ltoa(ercount));
  760.             printerr(" checksum errors!\n");
  761.             }
  762. #endif
  763.         }
  764.  
  765.     getline(linebuf, 512);
  766.  
  767.     if(strcmp(linebuf, "end"))
  768.         {
  769. #ifdef FINNISH
  770.         printerr("   `end'-rivi puuttuu!\n");
  771. #else
  772.         printerr("   No `end'-line!\n");
  773. #endif
  774.         ercount++;
  775.         }
  776.     else
  777.         getline(linebuf, 512);
  778.  
  779.     if(!strncmp(linebuf, "size ", 5))
  780.         {
  781.         if(atol(linebuf+5)!=size)
  782.             {
  783. #ifdef FINNISH
  784.             printerr("   Kokovirhe!\n");
  785. #else
  786.             printerr("   Size mismatch!\n");
  787. #endif
  788.             ercount++;
  789.             }
  790.  
  791.         *linebuf=0;
  792.         }
  793.  
  794.     if(resetuu) resetuudecodetab();
  795.  
  796.     return ercount==0;
  797.     }
  798.  
  799. static int decodefec(unsigned char *linebuf)
  800.     {
  801.     int start=1, f;
  802.     unsigned char outblock[7], *p;
  803.  
  804.     *linebuf=0;
  805.  
  806. #ifdef FINNISH
  807.     startoutput(linebuf+3, " (fipenkoodattu)\n");
  808. #else
  809.     startoutput(linebuf+3, " (fipencoded)\n");
  810. #endif
  811.  
  812.     for(;;)
  813.         {
  814.         if((f=fecdecoder())<0) break;
  815.  
  816.         if(start)
  817.             start=0;
  818.         else
  819.             put(outblock, 7);
  820.  
  821.         p=outblock;
  822.  
  823.         *p++=(f<<1)|(f=fecdecoder())>>6;
  824.         *p++=(f<<2)|(f=fecdecoder())>>5;
  825.         *p++=(f<<3)|(f=fecdecoder())>>4;
  826.         *p++=(f<<4)|(f=fecdecoder())>>3;
  827.         *p++=(f<<5)|(f=fecdecoder())>>2;
  828.         *p++=(f<<6)|(f=fecdecoder())>>1;
  829.         *p  =(f<<7)|fecdecoder();
  830.         }
  831.                 
  832.     put(outblock, -f);
  833.  
  834.     endoutput(0);
  835.  
  836.     return 1;
  837.     }
  838.  
  839. static int decodebtoa(unsigned char *linebuf)
  840.     {
  841.     unsigned char outblock[2][4];
  842.     int start=1, dataout=0, i=0, datasize, ok=1;
  843.  
  844.     *linebuf=0;
  845.  
  846. #ifdef FINNISH
  847.     startoutput("noname", " (btoa:ttu)\n");
  848. #else
  849.     startoutput("noname", " (btoa'd)\n");
  850. #endif
  851.  
  852.     while(btoadecoder(outblock[i]))
  853.         {
  854.         i=!i;
  855.  
  856.         if(start)
  857.             start=0;
  858.         else
  859.             {
  860.             put(outblock[i], 4);
  861.             dataout+=4;
  862.             }
  863.         }
  864.  
  865.     getline(linebuf, 512);
  866.  
  867.     if(strncmp(linebuf, "btoa End N ", 11))
  868.         {
  869. #ifdef FINNISH
  870.         printerr("   `btoa End'-rivi puuttuu!\n");
  871. #else
  872.         printerr("   No `btoa End'-line!\n");
  873. #endif
  874.         }
  875.     else
  876.         {
  877.         *linebuf=0;
  878.  
  879.         if((datasize=atol(linebuf+11))<dataout || datasize>dataout+4)
  880.             {
  881. #ifdef FINNISH
  882.             printerr("   Kokovirhe!\n");
  883. #else
  884.             printerr("   Size mismatch!\n");
  885. #endif
  886.             ok=0;
  887.             }
  888.         else
  889.             put(outblock[!i], datasize-dataout);
  890.         }
  891.  
  892.     endoutput(0);
  893.  
  894.     return ok;
  895.     }
  896.  
  897. static int fillbufferandprint(int yes)
  898.     {
  899.     int rc;
  900.  
  901.     if(lines && yes) writefile(stdoutfile, start, inptr-start);
  902.     rc=fillbuffer(1);
  903.     start=inptr;
  904.  
  905.     return rc;
  906.     }
  907.  
  908. int vdc(void)
  909.     {
  910.     int ok=1, lineswait=0;
  911.     unsigned char c, linebuf[512], *end;
  912.  
  913.     resetuudecodetab();
  914.  
  915.     start=inptr;
  916.  
  917.     for(;;)
  918.         {
  919.         /* check the first character of the line */
  920.  
  921.         do    {
  922.             if(inptr>=inbufend && !fillbufferandprint(!lineswait)) return ok;
  923.             c=*inptr++;
  924.             }
  925.         while(vws(c));
  926.  
  927.         if(lineswait)
  928.             {
  929.             lineswait=0;
  930.             start=inptr-1;
  931.             }
  932.  
  933.         if(c!='F' && c!='b' && c!='y' && c!='x' && c!='t')
  934.             {
  935.             /* find vertical white space character */
  936.  
  937.             nextline:
  938.  
  939.             do    {
  940.                 if(inptr>=inbufend && !fillbufferandprint(1)) return ok;
  941.                 c=*inptr++;
  942.                 }
  943.             while(!vws(c));
  944.  
  945.             continue;
  946.             }
  947.  
  948.         inptr--;
  949.  
  950.         /* ensure 512 characters or rest of file in the buffer */
  951.  
  952.         if(inptr>inbuf+bufsize-512)
  953.             {
  954.             long s;
  955.  
  956.             if(lines) writefile(stdoutfile, start, inptr-start);
  957.  
  958.             memcpy(inbuf, inptr, s=inbufend-inptr);
  959.             inbufend=inbuf+s;
  960.             fillbuffer(0);
  961.             inptr=start=inbuf;
  962.             }
  963.  
  964.         end=inptr++;
  965.  
  966.         /* get the line */
  967.  
  968.             {
  969.             char *p=linebuf;
  970.             int maxl=inbufend-inptr;
  971.  
  972.             if(maxl>511) maxl=511;
  973.  
  974.             do *p++=c, c=*inptr++; while(--maxl && !vws(c));
  975.  
  976.             *p=0;
  977.             }
  978.  
  979.         /* and test the magics */
  980.  
  981.         for(;;)
  982.             {
  983.             int (*func)(unsigned char *);
  984.  
  985.             if(!strncmp(linebuf, "yobufi", 6))
  986.                 func=decodevec;
  987.             else if(!strncmp(linebuf, "begin ", 6))
  988.                 func=decodeuu;
  989.             else if(!strncmp(linebuf, "table", 6))
  990.                 func=readuudecodetab;
  991.             else if(!strncmp(linebuf, "FEC", 3))
  992.                 func=decodefec;
  993.             else if(!strncmp(linebuf, "xbtoa Begin", 11))
  994.                 func=decodebtoa;
  995.             else
  996.                 {
  997.                 if(end) break;
  998.  
  999.                 if(!*linebuf)
  1000.                     lineswait=1;
  1001.                 else if(lines)
  1002.                     {
  1003.                     writefile(stdoutfile, linebuf, strlen(linebuf));
  1004.                     writefile(stdoutfile, &linedelim, 1);
  1005.                     }
  1006.  
  1007.                 start=inptr;
  1008.                 break;
  1009.                 }
  1010.  
  1011.             if(lines && end>start)
  1012.                 writefile(stdoutfile, start, end-start);
  1013.  
  1014.             end=0;
  1015.  
  1016.             ok&=func(linebuf);
  1017.             }
  1018.         }
  1019.     }
  1020.